import { useState, useContext } from "react";
import { useHistory } from "react-router-dom";

import Button from '../../components/Button';
import FormElem  from "../../components/FormElem";
import Header from "../../components/Header";
import Row from "../../components/Row";

import Side from '../common/Side';

import { ConnContext } from "../contexts/Conn";

import styles from './register.module.css';

const MailRegex = new RegExp(/^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)])$/);

const StrongPassRegex = new RegExp(/^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[!"#$%&'()*+,-./:;<=>?@_`{}~])[a-zA-Z0-9!"#$%&'()*+,-./:;<=>?@_`{}~]{8,}$/);

const MediumPassRegex = new RegExp(/^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9])[a-zA-Z0-9]{8,}$/);

const Register = () => {

  const history = useHistory();

  const {send, cast} = useContext(ConnContext);

  const [mail, setMail] = useState();
  const [pass, setPass] = useState();
  const [conf, setConf] = useState();
  const [fail, setFail] = useState({});

  const setFailField = (field, reason) => {
    setFail({...fail, [field]: reason});
  }

  const updateMail = (e) => {
    const mailString = e.target.value;
    setMail(mailString);

    if (mailString.match(MailRegex)) {
      setFailField('mail', undefined);
    } else {
      setFailField('mail', {stat: 'dead', msg:'邮箱格式不太对，请检查一下'});
    }
  }

  const updatePass = (e) => {
    const passString = e.target.value;
    setPass(passString);

    if (passString.match(StrongPassRegex)) {
      setFailField('pass', {stat: 'norm'});
    } else if (passString.match(MediumPassRegex)){
      setFailField('pass', {stat: 'warn', msg:'最好能同时包含数字、大小写字母及符号'});
    } else {
      setFailField('pass', {stat: 'dead', msg:'密码最短8个字符，且至少得包含1个大写字母、1个小写字母及1个数字'});
    }
  }

  const updateConf = (e) => {
    setConf(e.target.value);

    if (e.target.value !== pass) {
      setFailField('conf', {stat: 'dead', msg:'两次输入密码不一致'});
    } else {
      setFailField('conf', {stat: 'norm'});
    }
  }

  const recv = ({ok, code}) => {
    if (!ok) {
      const msg = {
        'REG.EXISTING': '用户名（邮箱）已经存在'
      }[code]

      setFail({...fail, pass:{stat: 'warn', msg}});
    } else {
      history.push('/log');
    }
  }

  const submit = () => {
    cast('auth.reg', recv);
    send('auth.reg', {mail, pass});
  }

  const toLog = () => {
    history.push('/log');
  }

  const isDisabled = Object.values(fail).some(f => f?.stat === 'dead');

  return <div className={styles['page']}>
    <Side />
    <div style={{margin: 10}}>
      <Header text='Register' />
      <FormElem type='text' label='Email' value={mail} {...fail.mail} onChange={updateMail}/>
      <FormElem type='password' label='Password' value={pass} {...fail.pass} onChange={updatePass}/>
      <FormElem type='password' label='Confirm' value={conf} {...fail.conf} onChange={updateConf}/>
      <Row>
        <Button isDisabled={isDisabled} onClick={submit}> Register </Button>
        <Button color='base03' isOutlined onClick={toLog}> to Login </Button>
      </Row>
    </div>
  </div>
}


export default Register;